package gat.application.dic.impl;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bitsun.core.common.exception.AppException;
import com.bitsun.core.common.exception.ErrorCode;
import com.bitsun.core.common.persistence.BasePService;
import com.bitsun.core.common.persistence.IPService;
import com.bitsun.core.common.persistence.Pager;
import com.bitsun.core.common.persistence.QueryParamUtils;
import com.google.common.base.CaseFormat;

import cn.hutool.core.collection.CollectionUtil;
import gat.application.dic.DicTypeService;
import gat.convertor.dic.DicTypeReqDtoConvertor;
import gat.convertor.dic.DicTypeResDtoConvertor;
import gat.dto.req.dic.DicTypeReqDto;
import gat.dto.res.dic.DicTypeResDto;
import gat.dto.res.dic.DicTypeVo;
import gat.infrastructure.persistence.dao.dic.DicTypeMapper;
import gat.infrastructure.persistence.po.dic.DicTypePo;
import lombok.extern.slf4j.Slf4j;
/**
 * 示例表，应用（业务编排）层实现
 * @author: tmac
 * @email: tmac
 */
@Slf4j
@Service("dicTypeAppService")
@Transactional(rollbackFor = Exception.class)
public class DicTypeServiceImpl implements DicTypeService {

    @Autowired
    private DicTypeReqDtoConvertor dicTypeReqDtoConvertor;

    @Autowired
    private DicTypeResDtoConvertor dicTypeResDtoConvertor;

    private IPService<DicTypePo> dicTypePoService;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    public DicTypeServiceImpl(DicTypeMapper dicTypeMapper) {
        this.dicTypePoService = new BasePService(dicTypeMapper);
    }



    @Override
    public DicTypeResDto save(DicTypeReqDto reqDto) {
        DicTypePo po = dicTypeReqDtoConvertor.dto2Po(reqDto);
        dicTypePoService.save(po);
        DicTypeResDto resDto = dicTypeResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean deleteByIds(String ids) {
        try {
            List<Long> idLongList =
            Arrays.asList(ids.split(",")).stream().map(s -> NumberUtils.createLong(s.trim())).collect(Collectors.toList());
            return dicTypePoService.removeByIds(idLongList);
        } catch (Exception e) {
            throw new AppException("参数错误：" + ids, ErrorCode.pc("417"), e);
        }
     }

    @Override
    public Pager<DicTypeResDto> doPager(Map<String, Object> params) {
        Pager<DicTypePo> poPager = dicTypePoService.queryPage(params, DicTypePo.class);
        Pager<DicTypeResDto> resDtoPager = dicTypeResDtoConvertor.convertPoPager2ResDtoPager(poPager);
        return resDtoPager;
    }

    @Override
    public DicTypeResDto selectOne(Long id) {
        DicTypePo po = dicTypePoService.getById(id);
        DicTypeResDto resDto = dicTypeResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public DicTypeResDto selectOne(Map<String, Object> params) {
        QueryWrapper queryWrapper = QueryParamUtils.queryWrapper4eq(DicTypePo::new, params);
        queryWrapper.last(" limit 1");
        DicTypePo po = dicTypePoService.getOne(queryWrapper);
        DicTypeResDto resDto = dicTypeResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean updateProps(Long id, Map<String, Object> params) {
        UpdateWrapper<DicTypePo> updateWrapper = QueryParamUtils.updateWrapper4Map(DicTypePo::new, id, params);
        return dicTypePoService.update(new DicTypePo(), updateWrapper);
        }

    @Override
    public boolean updateProps(Long id, DicTypeReqDto reqDto) {
        DicTypePo po = dicTypeReqDtoConvertor.dto2Po(reqDto);
        po.setId(id);
        return dicTypePoService.updateById(po);
    }


    @Override
    public boolean updateAllProps(Long id, DicTypeReqDto reqDto) {
        UpdateWrapper<DicTypePo> updateWrapper = Wrappers.update();
        updateWrapper.eq("id", id);
        Field[] fields = DicTypeReqDto.class.getDeclaredFields();
        Arrays.stream(fields).filter(f -> !Modifier.isStatic(f.getModifiers())).forEach(field -> {
        try {
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), DicTypeReqDto.class);
        Method getMethod = propertyDescriptor.getReadMethod();
        String fileNameCamel = getMethod.getName().substring(3);
        String fileNameUnderline = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fileNameCamel);
        updateWrapper.set(fileNameUnderline, getMethod.invoke(reqDto));
        } catch (Exception ex) {
        log.warn("属性不存在get方法："+field.getName(),ex);
        }
        });
        return dicTypePoService.update(new DicTypePo(), updateWrapper);
    }

    /**
     * 列表转树结构
     *
     * @return
     */
    @Override
    public List<DicTypeVo> getTree() {
        List<DicTypePo> poList = dicTypePoService.list(new QueryWrapper<>());
        List<DicTypeVo> list = new LinkedList<>();
        for (DicTypePo po : poList) {
            list.add(new DicTypeVo(po.getCode(), po.getDescription(), po.getPcode(), null, null));
        }
        Map<String, DicTypeVo> map = list.stream().collect(Collectors.toMap(DicTypeVo::getCode, a -> a));
        List<DicTypeVo> result = new LinkedList<>();
        list.forEach(l -> {
            if (Objects.isNull(l.getPcode())) {
                result.add(l);
            } else {
                if (CollectionUtil.isEmpty(map.get(l.getPcode()).getChildList())) {
                    List<DicTypeVo> child = new LinkedList<>();
                    child.add(l);
                    map.get(l.getPcode()).setChildList(child);
                } else {
                    map.get(l.getPcode()).getChildList().add(l);
                }
            }
        });
        return result;
    }

}